package P7.T08;

import java.util.concurrent.Semaphore;

public class T08 {
    public static void main(String[] args) {
        Reader[] readers = new Reader[10];
        Writer[] writers = new Writer[10];
        Monitor m=new Monitor();
        for(int i=0; i<10; i++){
            readers[i]=new Reader(m);
            readers[i].setName("读线程"+(i+1));
            writers[i]=new Writer(m);
            writers[i].setName("写线程"+(i+1));
            readers[i].setPriority(1);
            writers[i].setPriority(10);
            readers[i].start();
            writers[i].start();
        }
    }
}
class Monitor{

    private Semaphore runable=new Semaphore(1),readSem=new Semaphore(1);
    private int readCount=0;
    public Monitor(){
    }
    public void read() throws InterruptedException {
        if(readCount==0)runable.acquire();
        readSem.acquire();
        readCount++;
        System.out.printf("有%d个读者线程，当前线程为[%s]\n",readCount,Thread.currentThread().getName());
        readSem.release();
        System.out.printf("%s在读数据\n",Thread.currentThread().getName());
        Thread.sleep(0);
        readSem.acquire();
        readCount--;
        System.out.printf("读者线程退出，还剩%d个读者线程\n",readCount);
        if(readCount==0)runable.release();
        readSem.release();
    }
    public void write() throws InterruptedException {
        runable.acquire();
        System.out.printf("写者线程进入操作\n");
        System.out.printf("%s在写数据\n",Thread.currentThread().getName());
        System.out.printf("写者线程退出\n");
        runable.release();
    }
}
class Reader extends Thread{
    private Monitor m=null;

    public Reader(Monitor m) {
        this.m = m;
    }

    @Override
    public void run() {
        try {
            m.read();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}
class Writer extends Thread{
    private Monitor m=null;

    public Writer(Monitor m) {
        this.m = m;
    }

    @Override
    public void run() {
        try {
            m.write();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}